﻿using System;
using System.Net;
using System.IO;
using Utils;
using Utils.Extensions;

namespace StockAccessors.Interdin.Engine
{
    internal class ConnectionManager
    {
		#region Attributes

		private readonly string _user;
		private readonly string _password;

		#endregion

        #region Properties

        public CookieContainer Cookies { get; private set; }
		public int ContractNumber { get; private set; }

        #endregion

        #region Public Methods

        public ConnectionManager(string user, string password)
		{
			_user = user;
			_password = password;
		}

        public void Connect()
        {
			this.Cookies = new CookieContainer();
            this.NavigateHome();
            this.DoLogin();
        }

        public void Disconnect()
        {
            this.DoDisconnect();
        }

        #endregion

        #region Private Methods

        private void DoDisconnect()
        {
			using (HttpWebResponse response = HttpWebRequest2.SendGETRequest("https://www.interdinfuturos.com/Broker/Desconectar.asp", Properties.Settings.Default.UserAgent, this.Cookies, Properties.Settings.Default.ReadTimeout))
        	{
				// We don't need to read the response, not having the exception is enought to know that everything is ok
        	}
		}

        private void NavigateHome()
        {
			using (HttpWebResponse response = HttpWebRequest2.SendGETRequest("https://www.interdinfuturos.com/", Properties.Settings.Default.UserAgent, this.Cookies, Properties.Settings.Default.ReadTimeout))
			{
				// We don't need to read the response, not having the exception is enought to know that everything is ok
			}
        }

        private void DoLogin()
        {
			string textToSend = string.Format(@"Nombre={0}&Clave={1}&ok=Ok", _user, _password);
			using (HttpWebResponse response = HttpWebRequest2.SendPOSTRequest(textToSend, "https://www.interdinfuturos.com/Broker/Verificacion.asp", Properties.Settings.Default.UserAgent, this.Cookies, Properties.Settings.Default.ReadTimeout))
			{
				ConnectionManager.ValidateLogin(response);
				this.ContractNumber = Int32.Parse(response.ResponseUri.ToString().Substring(response.ResponseUri.ToString().IndexOf('=') + 1));
			}
        }

		// If the login is invalid an exception will be raised so we don't need to return anything
		private static void ValidateLogin(HttpWebResponse response)
		{
			string responseContent;
			using (Stream webStream = response.GetResponseStream())
			{
				responseContent = webStream.ReadTextResponse(response.CharacterSet);
			}

			if (ConnectionManager.IsWrongUserPasswordResponse(responseContent))
			{
				InvalidConnectionDataException ex = new InvalidConnectionDataException();
				ex.Data.Add("response", responseContent);
				throw ex;
			}
			else if (!ConnectionManager.IsValidResponseUrl(response.ResponseUri.ToString()))
			{
				InvalidDataException ex = new InvalidDataException("The retrieved page " + response.ResponseUri.ToString() + " is not the expected one");
				ex.Data.Add("responseUrl", response.ResponseUri.ToString());
				ex.Data.Add("response", responseContent);
				throw ex;
			}
		}

        private static bool IsValidResponseUrl(string responseURL)
        {
            return responseURL.StartsWith("https://www.interdinfuturos.com/Broker/Futuros.asp?nc=");
        }

		private static bool IsWrongUserPasswordResponse(string response)
		{
			return response.Contains("Se ha producido un error al acceder con su usuario y contraseña");
		}

        #endregion
    }
}
